﻿using Forum.Cache;
using Forum.Infrastructure.Util;
using Forum.Model;
using Forum.Model.Entity;
using Forum.Model.Pager;
using Forum.Model.Request;
using Forum.Repository.Extensions;
using Forum.Repository.Interface;
using Forum.Service.Interface;
using Markdig;
using Markdig.Renderers.Normalize;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Net;

namespace Forum.Service.Service
{
    public class PostService : IPostService
    {
        private readonly IAppRepository<Post> _postRepo;
        private readonly IAppRepository<Category> _categoryRepo;
        private readonly IWebHostEnvironment _environment;
        private readonly IConfiguration _configuration;
        private readonly IHttpContextAccessor _accessor;
        private readonly LinkGenerator _generator;
        private readonly ILogger<PostService> _log;

        public PostService(IAppRepository<Post> postRepo,
            IAppRepository<Category> categoryRepo,
            IWebHostEnvironment environment,
            IConfiguration configuration,
            IHttpContextAccessor accessor,
            LinkGenerator generator,
            ILogger<PostService> log
        )
        {
            _postRepo = postRepo;
            _categoryRepo = categoryRepo;
            _environment = environment;
            _configuration = configuration;
            _accessor = accessor;
            _generator = generator;
            _log = log;
        }

        /// <summary>
        /// 根据ID查询博客
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Post? GetById(string id)
        {
            // 获取文章的时候对markdown中的图片地址解析，加上完整地址返回给前端
            var post = _postRepo.SugarQueryable.Includes(a => a.Category).Where(a => a.Id == id).First();

            //获取缓存的改文章点击量
            var num = CacheFactory.Cache.GetCache<int>(id) + 1;
            if (num > post.ViewsCount)
            {
                post.ViewsCount = num;
                CacheFactory.Cache.SetCache<int>(id, num);//点击量+1
            }
            else
                CacheFactory.Cache.SetCache<int>(id, post.ViewsCount);//缓存重新设置成数据库的

            if (post != null)
            {
                post.Content = MdImageLinkConvert(post, true);
                post.ContentHtml = Markdig.Markdown.ToHtml(post.Content);
            }


            //if (!string.IsNullOrWhiteSpace(post.ContentHtml))
            //{
            //    ConvertImg(post.ContentHtml)
            //}


            return post;
        }

        /// <summary>
        /// 查询博客浏览量
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public int GetViewsCount(string id)
        {
            var num = CacheFactory.Cache.GetCache<int>("id");
            CacheFactory.Cache.SetCache<int>(id, num + 1);
            return num;
        }

        /// <summary>
        /// 删除博客
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Delete(string id)
        {
            return _postRepo.Delete(a => a.Id == id);
        }

        /// <summary>
        /// 插入博客
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public Post Insert(Post post)
        {
            // 修改文章时，将markdown中的图片地址替换成相对路径再保存
            post.Content = MdImageLinkConvert(post, false);
            var a = _postRepo.Insert(post);
            return post;
        }

        public Post Update(Post post)
        {
            // 修改文章时，将markdown中的图片地址替换成相对路径再保存
            //post.Content = MdImageLinkConvert(post, false);
            var a = _postRepo.Updateable(post).IgnoreColumns(a => a.CreationTime).ExecuteCommand();
            return post;
        }

        /// <summary>
        /// 指定文章上传图片
        /// </summary>
        /// <param name="post"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        public string UploadImage(IFormFile file)
        {
            InitPostMediaDir();

            var filename = WebUtility.UrlEncode(file.FileName);
            var fileRelativePath = Path.Combine("media", "blog", filename);
            var savePath = Path.Combine(_environment.WebRootPath, fileRelativePath);
            if (File.Exists(savePath))
            {
                // 上传文件重名处理
                var newFilename = $"{Path.GetFileNameWithoutExtension(filename)}-{GuidUtils.GuidTo16String()}{Path.GetExtension(filename)}";
                fileRelativePath = Path.Combine("media", "blog", newFilename);
                savePath = Path.Combine(_environment.WebRootPath, fileRelativePath);
            }

            using (var fs = new FileStream(savePath, FileMode.Create))
            {
                file.CopyTo(fs);
            }

            _log.LogInformation($"地址：{SystemConfig.imageUrl}，路径：{fileRelativePath}");

            return Path.Combine(SystemConfig.imageUrl, fileRelativePath);
        }

        /// <summary>
        /// 获取指定文章的图片资源
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public List<string> GetImages(Post post)
        {
            var data = new List<string>();
            var postDir = InitPostMediaDir();
            foreach (var file in Directory.GetFiles(postDir))
            {
                data.Add(Path.Combine(SystemConfig.imageUrl, "media", "blog", Path.GetFileName(file)));
            }

            return data;
        }

        /// <summary>
        /// 分页查询所有博客
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public IPagedList<Post> GetPagedList(PostQueryParameters param)
        {
            var querySet = _postRepo.SugarQueryable.Includes(a => a.Category).Includes(a => a.StatusOption);

            // 状态过滤
            if (param.Status != null)
            {
                querySet = querySet.Where(a => a.Status == param.Status.Value);
            }
            // 分类过滤
            if (param.CategoryId != 0)
            {
                querySet = querySet.Where(a => a.CategoryId == param.CategoryId);
            }
            // 关键词过滤
            if (!string.IsNullOrEmpty(param.Search))
            {
                querySet = querySet.Where(a => a.Title.Contains(param.Search));
            }
            // 排序
            querySet = querySet.OrderByDescending(a => a.IsTop);
            if (!string.IsNullOrEmpty(param.SortBy))
            {
                // 是否升序
                var ascending = !param.SortBy.StartsWith("-") ? " asc" : " desc";
                var orderByProperty = param.SortBy.Trim('-');

                querySet = querySet.OrderBy(orderByProperty + ascending);
            }

            var postList = querySet.ToPage(param.Page, param.PageSize);

            foreach (var item in postList)
            {
                //将默认图片替换成随机一张图片
                var banner = item.Banner;
                Random r = new Random();
                var index = banner.LastIndexOf('/');
                item.Banner = banner.Remove(index + 1).Insert(index + 1, r.Next(1, 17).ToString()) + ".jpg";

                var num = CacheFactory.Cache.GetCache<int>(item.Id);//获取缓存中的浏览量
                if (num > item.ViewsCount)
                    item.ViewsCount = num;
                else
                    CacheFactory.Cache.SetCache(item.Id, item.ViewsCount);
            }
            return postList;
        }

        /// <summary>
        /// 初始化博客文章的资源目录
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        private string InitPostMediaDir()
        {
            var blogMediaDir = Path.Combine(_environment.WebRootPath, "media", "blog");
            if (!Directory.Exists(blogMediaDir)) Directory.CreateDirectory(blogMediaDir);

            return blogMediaDir;
        }

        /// <summary>
        /// Markdown中的图片链接转换
        /// </summary>
        /// <param name="post"></param>
        /// <param name="isAddPrefix"></param>
        /// <returns></returns>
        private string MdImageLinkConvert(Post post, bool isAddPrefix = true)
        {
            var document = Markdown.Parse(post.Content);

            foreach (var node in document.AsEnumerable())
            {
                if (node is not ParagraphBlock { Inline: { } } paragraphBlock) continue;
                foreach (var inline in paragraphBlock.Inline)
                {
                    if (inline is not LinkInline { IsImage: true } linkInline) continue;

                    var imgUrl = linkInline.Url;
                    if (imgUrl == null) continue;
                    if (isAddPrefix && imgUrl.StartsWith("http")) continue;
                    if (isAddPrefix)
                    {
                        if (imgUrl.StartsWith("http")) continue;
                        // 设置完整链接
                        linkInline.Url = $"{SystemConfig.imageUrl}/media/blog/{imgUrl}";
                    }
                    else
                    {
                        // 设置成相对链接
                        linkInline.Url = Path.GetFileName(imgUrl);
                    }
                }
            }

            using var writer = new StringWriter();
            var render = new NormalizeRenderer(writer);
            render.Render(document);
            return writer.ToString();
        }


    }
}
